interface Person {
  name: string;
  age: number;
}
/**
 * typeof 用来获取一个变量声明或者对象的类型
 */
const obj = {
  name: '',
  age: 1,
};

const func = (name: number) => name;
type objType = typeof obj;
type funcType = typeof func;

/**
 * 2 keyof 用来获取数据类型的所有键，返回值类型是联合类型： 'a' | 'b' | 'c'
 */
type keys = keyof Person;

/**
 * 3 in 用來遍历枚举类型（联合类型）
 */
type CloneP = {
  [K in keys]: any;
};

/**
 * 4 infer 用來遍推断某个类型（运行时确定类型）
 */
type ReturnType<T extends (...args: any[]) => any> = T extends (...args: any[]) => infer R
  ? R
  : any;
type t = ReturnType<funcType>;

/**
 * 5 extends 用來遍约束泛型范围的
 */

// 全部变成可选类型
type Partail<T> = {
  [K in keyof T]?: T[K];
};

/* const b = BigInt(2);
const sum = b + 1n;
console.log(sum);
let aa: void = null;
aa = undefined; */

// 类型断言和类型守卫
const obj1 = {} as Person;

// 类型守卫
// 1 instanceof
if (obj instanceof Object) {
  // do something
}
// 2 in
if ('name' in obj1) {
  // do something
}
// 3 字面量类型守卫
type Foo = {
  type: 'foo';
  name: string;
  func(): void;
  func1(): void;
};
/* const foo: Foo = { type: 'foo', name: '' };
if (foo.type === 'foo') {
  // dosomething
} */

type Partial<T> = {
  [K in keyof T]?: T[K];
};

/**
如果添加是裸条件的类型，那么就会返回一个联合类型
*/
type Diff<T, U> = T extends U ? never : T;
type a = Diff<'a' | 'b', 'a' | 'c'>; // 返回'b'

// 获取一个接口中属性是函数的key集合
type FunctionPropsNames<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type aa = FunctionPropsNames<Foo>;

type NullableKeys<T> = {
  [K in keyof T]: T[K] extends Function ? K : never;
};

// 实现tuple转uniom
type ChangeUnion<T> = T extends Array<infer P> ? P : T;
type aaa = ChangeUnion<[number, string]>;
export const aaaa = 0;
